#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include "cargarImagenes.h"
#include "resizeImagenes.h"
#include "algoritmos.h"
#include <time.h>

using namespace std;

double psnr;

void sacarRuido(FILE * imagenAFiltrar, float lambda){
    vector<float> x;
    pair<Matriz, vector<float> > tuplaCargada;

    FILE * imagenNueva = fopen("./ImagenFiltrada.pgm", "w+");

    tuplaCargada = crearAyB(imagenAFiltrar,lambda,imagenNueva);

    cout << "Empezo Gauss" << endl;
    x = gauss(tuplaCargada.first, tuplaCargada.second);
    cout << "Termino Gauss" << endl << endl;

    ///Meto los pixeles en el archivo.
    for (int i=0; i<(int)x.size(); i++)
    {
        cout << x[i] << endl;
        fputc((int)x[i], imagenNueva);
    }

    fclose(imagenNueva);
}

double calcPSNR(FILE * imagen, FILE * imagenNueva)
{
    Foto fotoImagen;
    fotoImagen.guardarImagen(imagen);

    Foto fotoImagenNueva;
    fotoImagenNueva.guardarImagen(imagenNueva);

    return PSNR(fotoImagen,fotoImagenNueva);
}

double calcularPSNR(char* fileName) {
	/// Abrimos la imagen a ampliar.
	FILE * imagenOriginal = fopen(fileName, "r");

	if (imagenOriginal == NULL)
		perror ("Error abriendo la imagen original");
	else
	{
		/// Abrimos la imagen a ampliar.
		FILE * imagenFinal = fopen("./salidaSobreMuestreo.pgm", "r");

		if (imagenFinal == NULL)
			perror ("Error abriendo la imagen final");
		else
		{
			psnr = calcPSNR(imagenOriginal,imagenFinal);
			fclose(imagenFinal);
		}
		fclose(imagenOriginal);
	}

	return psnr;
}

int main(int argc, char* argv[])
{
    char *fileName;
    float lambda;
    int fr;
    clock_t init, final;
    init = clock();
    
    if (argc != 3 && argc != 4)
    {
        cout << "Cantidad de parametros erronea" << endl;
        cout << "Para reducir el ruido:" << endl;
        cout << "   ./main imagenes/64x64/blond.pgm lambda" << endl << endl;
        cout << "Para reducir el ruido y la imagen:" << endl;
        cout << "   ./main imagenes/64x64/blond.pgm lambda factor_reduccion" << endl;
    }
    else
    {
        if (argc == 3)
        {
            fileName = argv[1];
            lambda = atof(argv[2]);

            FILE * imagen = fopen(fileName, "r");

            if (imagen == NULL)
                perror ("Error opening file");
            else
            {
                cout << "Abrimos el archivo: " << fileName << endl;
                cout << "Lambda: " << lambda << endl;

                sacarRuido(imagen, lambda);
                
				/// Abrimos la imagen a la que le sacamos el ruido.
				FILE * imagenFiltrada = fopen("./ImagenFiltrada.pgm", "r");
				
				if (imagenFiltrada == NULL)
					perror ("Error abriendo la imagen filtrada");
				else
				{
					psnr = calcPSNR(imagen, imagenFiltrada);
					cout << "PSNR: " << psnr << endl;
					
					fclose(imagenFiltrada);
				}
				fclose(imagen);
            }
        }
        else
        {
            fileName = argv[1];
            lambda = atof(argv[2]);
            fr = atoi(argv[3]);

            /// Abrimos la imagen a reducir de tamaño.
            FILE * imagenAReducir;
            imagenAReducir = fopen(fileName, "r");

            if (imagenAReducir == NULL)
                perror ("Error abriendo la imagen a reducir de tamaño");
            else
            {
                cout << "Lambda: " << lambda << endl;
                cout << "Factor reduccion: " << fr << endl << endl;
                cout << "Abrimos el archivo: " << fileName << endl;

                /// Aplicamos la reduccion de tamaño.
                subMuestreo(imagenAReducir, fr);

                fclose(imagenAReducir);

                /// Abrimos la imagen a filtrar.
                FILE * imagenAFiltrar = fopen("./salidaSubMuestreo.pgm", "r");
                if (imagenAFiltrar == NULL)
                    perror ("Error abriendo la imagen a filtrar");
                else
                {
                    cout << "Abrimos el archivo: " << "./salidaSubMuestreo.pgm" << endl;

                    /// Aplicamos la reduccion de ruido.
                    sacarRuido(imagenAFiltrar, lambda);

                    fclose(imagenAFiltrar);

                    /// Abrimos la imagen a ampliar.
                    FILE * imagenFiltrada = fopen("./ImagenFiltrada.pgm", "r");
					
                    if (imagenFiltrada == NULL)
                        perror ("Error abriendo la imagen filtrada");
                    else
                    {
                        cout << "Abrimos el archivo: " << "./ImagenFiltrada.pgm" << endl;

                        /// Aplicamos la ampliacion de tamaño.
                        sobreMuestreo(imagenFiltrada, fr);

                        fclose(imagenFiltrada);
                        
						ofstream pepe;
						pepe.open("./RESULTADOS.txt",ios::app);
						final=clock()-init;
						pepe << "Archivo: " << fileName << "\t Lambda: " << (float)lambda << "\t Fr: " << fr << "\t tiempo: " << (double)final / ((double)CLOCKS_PER_SEC) << "\t PSNR: " << calcularPSNR(fileName) << endl;

                    }

                }

            }

        }

    }

    return 0;
}

